#include "Edge.h"
#include "Random.h"


std::map<Point*, std::set<Edge*, cmp_Edge_ptr>> Edge::Graph;

Edge::Edge() :p1(nullptr), p2(nullptr), n(0), v(0) {}

Edge::Edge(Point* _p1, Point* _p2) :p1(_p1), p2(_p2) {
	n = Random::rnd() % 250;
	v = max(Random::rnd() % 100 + 1,50);
}
Edge::Edge(Point* _p1, Point* _p2, int _n, int _v) :p1(_p1), p2(_p2), v(_v), n(_n) {}

Edge::~Edge() {}

Point* Edge::get_p1() const {
	return p1;
}
Point* Edge::get_p2() const {
	return p2;
}

double Edge::get_n() const
{
	return this->n;
}

double Edge::get_v() const
{
	return this->v;
}

double Edge::get_len() const
{
	return sqrt(sqr(p1->get_x() - p2->get_x()) + sqr((p1->get_y() - p2->get_y())));
}

std::map<Point*, std::set<Edge*, cmp_Edge_ptr>>* Edge::graph() {
	return &Graph;
}

Edge Edge::reverse() const
{
	return Edge(this->p2, this->p1);
}

double Edge::get_cost() const
{
	if (n <= v)
		return get_len();
	return get_len() * (1 + exp(1) * n / v);
}

void Edge::set_p1(Point* _p1) {
	this->p1 = _p1;
}

void Edge::set_p2(Point* _p2) {
	this->p2 = _p2;
}


void Edge::set_n(const double _n) {
	this->n = _n;
}

void Edge::set_v(const double _v) {
	this->v = _v;
}

void add_Edge(Edge& e)
{
	Edge* e_ptr = new Edge(e.get_p1(), e.get_p2(), e.get_n(), e.get_v());
	(*Edge::graph())[e.get_p1()].emplace(e_ptr);
	Edge* e_ptr_r = new Edge(e.get_p2(), e.get_p1(), e.get_n(), e.get_v());
	(*Edge::graph())[e.get_p2()].emplace(e_ptr_r);
}

void del_Edge(Edge& e)
{
	Edge* e_ptr = &e;
	auto P = (*Edge::graph())[e.get_p1()].find(e_ptr);


	Edge e_r(e.get_p2(), e.get_p1(), e.get_n(), e.get_v());
	Edge* e_ptr_r = &e_r;
	auto P_r = (*Edge::graph())[e_r.get_p1()].find(e_ptr_r);

	Edge* ptr = *P;
	Edge* ptr_r = *P_r;

	(*Edge::graph())[e_r.get_p1()].erase(P_r);
	delete ptr_r;

	(*Edge::graph())[e.get_p1()].erase(P);
	delete ptr;
}
